package jxtend.processor.eclipse;

import static java.util.Arrays.asList;

import java.util.Arrays;
import java.util.List;

import jxtend.processor.eclipse.visitor.handler.ASTNodeVisitorHandler;
import jxtend.processor.eclipse.visitor.handler.impl.ArrayReferenceOnListOrMapHandler;
import jxtend.processor.eclipse.visitor.handler.impl.EqualsAndHashCodeHandler;
import jxtend.processor.eclipse.visitor.handler.impl.GenericAnnotationHandler;
import jxtend.processor.eclipse.visitor.handler.impl.ImplicitFinalLocalDeclarationHandler;
import jxtend.processor.eclipse.visitor.handler.impl.OverrideAnnotationHandler;
import jxtend.processor.eclipse.visitor.handler.impl.PropertyHandler;
import jxtend.processor.eclipse.visitor.handler.impl.SAMTypeInstantiationShorthandHandler;
import jxtend.processor.eclipse.visitor.handler.impl.SuppressWarningsAliasAnnotationHandler;
import jxtend.processor.eclipse.visitor.handler.impl.ToStringHandler;
import jxtend.processor.eclipse.visitor.handler.impl.TypeInferenceHandler;
import jxtend.processor.eclipse.visitor.replace.ASTNodeReplaceHandler;
import jxtend.processor.eclipse.visitor.replace.AnnotationReplaceHandler;
import jxtend.processor.eclipse.visitor.replace.AnnotationTypeReplaceHandler;
import jxtend.processor.eclipse.visitor.replace.ExpressionReplacer;
import jxtend.processor.eclipse.visitor.replace.LocalDeclarationTypeReplacer;
import jxtend.processor.eclipse.visitor.replace.QualifiedAllocationExpressionTypeReplacer;
import jxtend.processor.eclipse.visitor.traverser.ASTNodeChildrenTraverser;
import jxtend.processor.eclipse.visitor.traverser.ForeachStatementTraverser;
import jxtend.processor.eclipse.visitor.traverser.LocalDeclarationTraverser;
import jxtend.processor.eclipse.visitor.traverser.MethodDeclarationTraverser;
import jxtend.processor.eclipse.visitor.traverser.TryStatementTraverser;
import jxtend.processor.eclipse.visitor.traverser.TypeDeclarationTraverser;

import com.google.inject.AbstractModule;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;

public class BuiltInHandlerModule extends AbstractModule {

	private static final TypeLiteral<List<ASTNodeChildrenTraverser>> astNodeChildrenTraverserType =
		new TypeLiteral<List<ASTNodeChildrenTraverser>>() {};

	private static final TypeLiteral<List<ASTNodeReplaceHandler>> astNodeReplaceHandlerType =
		new TypeLiteral<List<ASTNodeReplaceHandler>>() {};

    private static final TypeLiteral<List<ASTNodeVisitorHandler>> astNodeVisitorHandlerType =
    	new TypeLiteral<List<ASTNodeVisitorHandler>>() {};


	@Override protected void configure() {
		List<ASTNodeChildrenTraverser> astNodeChildrenTraversers = asList(new LocalDeclarationTraverser(),
				new ForeachStatementTraverser(), new TryStatementTraverser(), new MethodDeclarationTraverser(),
				new TypeDeclarationTraverser());
		bind(Key.get(astNodeChildrenTraverserType)).toInstance(astNodeChildrenTraversers);


		List<ASTNodeReplaceHandler> astNodeReplaceHandlers = Arrays.<ASTNodeReplaceHandler>asList(
				new AnnotationReplaceHandler(), new AnnotationTypeReplaceHandler(),
				new QualifiedAllocationExpressionTypeReplacer(), new LocalDeclarationTypeReplacer(),
				new ExpressionReplacer());
		bind(Key.get(astNodeReplaceHandlerType)).toInstance(astNodeReplaceHandlers);


		List<ASTNodeVisitorHandler> astNodeHandlers = Arrays.<ASTNodeVisitorHandler>asList(
				new SAMTypeInstantiationShorthandHandler(), new GenericAnnotationHandler(), new PropertyHandler(),
				new ImplicitFinalLocalDeclarationHandler(),
				new TypeInferenceHandler(),
//				new ImplicitNotNullHandler(),
				new OverrideAnnotationHandler(),/* new CastAnnotationHandler(),*/
				new SuppressWarningsAliasAnnotationHandler(),
				new ArrayReferenceOnListOrMapHandler(),
				new EqualsAndHashCodeHandler(),
				new ToStringHandler() //,
//				new ChainedCastingHandler(),
//				new ChainedInstanceOfHandler()
				);
		bind(Key.get(astNodeVisitorHandlerType)).toInstance(astNodeHandlers);
	}
}
